package com.example.yx1.demo36;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.http11.Http11Nio2Protocol;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;

public class A36 {
    public static void main(String[] args) throws IOException, LifecycleException {
        //1.创建Tomcat对象
        Tomcat tomcat = new Tomcat();
        tomcat.setBaseDir("tomcat");//放置那些生成的文件夹等，设置基础路径

        //2.创建项目文件夹,即docBase
        File docBase = Files.createTempDirectory("boot.").toFile(); //临时目录，给Context用
        docBase.deleteOnExit(); //程序退出时自动删除

        //3.创建Tomcat项目，在Tomcat为Context
        Context context = tomcat.addContext("", docBase.getAbsolutePath());//默认 为 "/"
        WebApplicationContext springContext = getApplicationContext();

        //4，编程添加Servlet
        context.addServletContainerInitializer(new ServletContainerInitializer() {
            @Override
            public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
                ctx.addServlet("hello",new HelloServlet()).addMapping("/hello");
//                DispatcherServlet bean = springContext.getBean(DispatcherServlet.class);
//                ctx.addServlet("dispatcherServlet",bean).addMapping("/");

                //扫描所有的注册Bean，并让 DispatcherServletRegistrationBean 进行自动注册,ServletRegistrationBean 是它的父类
                for (ServletRegistrationBean registrationBean : springContext.getBeansOfType(ServletRegistrationBean.class).values()) {
                    registrationBean.onStartup(ctx);
                }

            }
        }, Collections.emptySet());
        //5.启动Tomcat
        tomcat.start();

        //6.创建连接器，设置监听端口
        Connector connector = new Connector(new Http11Nio2Protocol());
        connector.setPort(8080);
        tomcat.setConnector(connector);
    }

    public static WebApplicationContext getApplicationContext() {
        AnnotationConfigServletWebApplicationContext context = new AnnotationConfigServletWebApplicationContext();
        context.register(Config.class);
        context.refresh();
        return context;

    }

    @Configuration
    static class Config {
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet,"/");
        }

        @Bean
        //必须提供 WebApplicationContext ，否则会走Xml
        public DispatcherServlet dispatcherServlet(WebApplicationContext webApplicationContext) {
            return new DispatcherServlet(webApplicationContext);
        }

        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter () {
            RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
            List<HttpMessageConverter<?>> list = new ArrayList<>();
            list.add(new MappingJackson2HttpMessageConverter());
            handlerAdapter.setMessageConverters(list);
            return handlerAdapter;
        }

        @RestController
        static class MyController {
            @GetMapping("/hello2")
            public Map<String,Object> hello() {
                Map<String,Object>  map = new HashMap();
                map.put("hello2","hello2,spring!");
                return map;
            }

        }
    }
}
